package org.lemon.cla.controller;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.lemon.cla.enums.HttpStatusEnum;
import org.lemon.cla.dto.response.ResponseResult;
import org.lemon.cla.dto.request.FeedbackCreateRequest;
import org.lemon.cla.dto.request.FeedbackUpdateRequest;
import org.lemon.cla.dto.request.FeedbackSearchRequest;
import org.lemon.cla.exception.BusinessException;
import org.lemon.cla.pojo.Feedback;
import org.lemon.cla.pojo.User; // 导入 User 实体
import org.lemon.cla.vo.FeedbackVo; // 导入 FeedbackVo
import org.lemon.cla.enums.FeedbackTypeEnum;
import org.lemon.cla.enums.FeedbackStatusEnum;
import org.lemon.cla.service.IFeedbackService;
import org.lemon.cla.service.IUserService; // 导入 IUserService
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import jakarta.validation.Valid;

import java.time.LocalDateTime;
import java.util.Optional; // 导入Optional


@RestController
@RequestMapping("/api/feedbacks")
@Tag(name = "应用反馈管理", description = "提供应用反馈信息的 CRUD 和查询接口")
public class FeedbackController {

    @Autowired
    private IFeedbackService feedbackService;
    @Autowired
    private IUserService userService; // 注入 IUserService

    @Operation(summary = "获取所有反馈", description = "分页获取所有反馈列表，**包含申请人信息 (若用户被逻辑删除则显示为未知)**")
    @GetMapping
    public ResponseResult<IPage<FeedbackVo>> getAllFeedbacks(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页数量", example = "10") @RequestParam(defaultValue = "10") Integer pageSize) {
        Page<FeedbackVo> page = new Page<>(pageNum, pageSize);
        IPage<FeedbackVo> feedbackPage = feedbackService.getAllFeedbacksVo(page);
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), feedbackPage);
    }

    @Operation(summary = "根据ID获取反馈", description = "根据反馈ID获取反馈详情，**包含申请人信息 (若用户被逻辑删除则显示为未知)**")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "成功获取反馈"),
            @ApiResponse(responseCode = "404", description = "反馈未找到")
    })
    @GetMapping("/{id}")
    public ResponseResult<FeedbackVo> getFeedbackById(
            @Parameter(description = "反馈ID", required = true, example = "1") @PathVariable Long id) {
        // 使用Optional简化null检查，如果未找到则抛出异常
        return Optional.ofNullable(feedbackService.getFeedbackVoById(id))
                .map(feedbackVo -> ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), feedbackVo))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "反馈未找到。")); // 抛出异常
    }

    @Operation(summary = "创建新反馈", description = "创建一个新的应用反馈记录 (**用户不能是逻辑删除状态**，自动设置创建时间、初始状态为待处理)")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "201", description = "反馈创建成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误 (如校验失败)"),
            @ApiResponse(responseCode = "404", description = "用户不存在或已逻辑删除"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PostMapping
    @PreAuthorize("isAuthenticated()") // 认证用户才能创建反馈
    public ResponseResult<Feedback> createFeedback(
            @Parameter(description = "应用反馈创建请求对象 (无需传入 feedbackId, createTime, status, reply, replyTime)", required = true)
            @RequestBody @Valid FeedbackCreateRequest request) {

        // 业务校验：用户是否存在且未被逻辑删除
        Optional.ofNullable(userService.getById(request.getUserId().intValue()))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.CONFLICT.getCode(), "反馈创建失败：用户不存在或已逻辑删除。"));

        Feedback feedback = new Feedback();
        BeanUtils.copyProperties(request, feedback);

        feedback.setCreateTime(LocalDateTime.now());
        feedback.setStatus(FeedbackStatusEnum.PENDING); // 默认新反馈状态为“待处理”

        boolean success = feedbackService.save(feedback);
        if (!success) { // 如果保存操作返回false但没有异常抛出
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "反馈创建失败，请稍后重试。"); // 抛出异常
        }
        return ResponseResult.success(HttpStatusEnum.CREATED.getCode(), HttpStatusEnum.CREATED.getMessage(), feedback);
    }

    @Operation(summary = "更新反馈", description = "根据反馈ID更新反馈信息（用户可修改，不包括状态和回复）")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "反馈更新成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误或试图修改状态/回复字段"),
            @ApiResponse(responseCode = "404", description = "反馈未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/{id}")
    @PreAuthorize("isAuthenticated()") // 认证用户才能修改自己的反馈
    public ResponseResult<Feedback> updateFeedback(
            @Parameter(description = "反馈ID", required = true, example = "1") @PathVariable Long id,
            @Parameter(description = "更新后的反馈对象", required = true) @RequestBody @Valid FeedbackUpdateRequest request) {

        Feedback existingFeedback = Optional.ofNullable(feedbackService.getById(id))
                .orElseThrow(() -> new BusinessException(HttpStatusEnum.NOT_FOUND.getCode(), "反馈未找到。"));

        // 业务校验：不允许通过此接口修改状态或回复字段
        if (request.getContact() != null) {
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "不允许通过此接口修改反馈状态或管理员回复。");
        }

        // 可以添加权限校验：只有反馈的提交者才能修改自己的反馈 (可选)
        // 例如：@AuthenticationPrincipal User currentUser; if (!currentUser.getUserId().equals(existingFeedback.getUserId().intValue())) { throw new AccessDeniedException("无权修改他人反馈"); }

        // 仅更新允许的字段 (例如：反馈类型、内容、联系方式)
        Optional.ofNullable(request.getFeedbackType())
                .ifPresent(existingFeedback::setFeedbackType);
        Optional.ofNullable(request.getContent())
                .ifPresent(existingFeedback::setContent);
        Optional.ofNullable(request.getContact())
                .ifPresent(existingFeedback::setContact);

        boolean success = feedbackService.updateById(existingFeedback);
        if (!success) { // 如果更新返回false
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "反馈更新失败，请稍后重试。"); // 抛出异常
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), existingFeedback);
    }

    @Operation(summary = "删除反馈", description = "根据反馈ID删除反馈。")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "204", description = "反馈删除成功"),
            @ApiResponse(responseCode = "404", description = "反馈未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('管理员')") // 通常只有管理员能删除反馈
    public ResponseResult<Void> deleteFeedback(
            @Parameter(description = "反馈ID", required = true, example = "1") @PathVariable Long id) {
        boolean success = feedbackService.removeById(id);
        if (!success) { // 如果删除返回false
            throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "反馈未找到或删除失败。"); // 抛出异常
        }
        return ResponseResult.success(HttpStatusEnum.NO_CONTENT.getCode(), HttpStatusEnum.NO_CONTENT.getMessage(), null);
    }

    @Operation(summary = "模糊查询反馈(查询首选)", description = "根据用户ID、类型、内容、联系方式、时间范围、状态、回复进行模糊查询，**返回包含申请人信息 (若用户被逻辑删除则显示为未知)**")
    @PostMapping("/search")
    public ResponseResult<IPage<FeedbackVo>> searchFeedbacks(
            @Parameter(description = "页码", example = "1") @RequestParam(defaultValue = "1") Integer pageNum,
            @Parameter(description = "每页数量", example = "10") @RequestParam(defaultValue = "10") Integer pageSize,
            @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "反馈查询请求对象 (可选，用于筛选)",
                    required = false,
                    content = @Content(schema = @Schema(implementation = FeedbackSearchRequest.class))
            ) @org.springframework.web.bind.annotation.RequestBody FeedbackSearchRequest request) {

        Page<FeedbackVo> page = new Page<>(pageNum, pageSize);

        // 使用Optional简化，确保request总是一个非null的实例
        request = Optional.ofNullable(request).orElseGet(FeedbackSearchRequest::new);

        IPage<FeedbackVo> resultPage = feedbackService.searchFeedbacksByConditions(page, request);

        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), HttpStatusEnum.SUCCESS.getMessage(), resultPage);
    }

    @Operation(summary = "处理反馈（管理员操作）", description = "根据反馈ID更新反馈的处理状态和管理员回复。")
    @ApiResponses(value = {
            @ApiResponse(responseCode = "200", description = "反馈处理成功"),
            @ApiResponse(responseCode = "400", description = "请求参数错误或状态值无效"),
            @ApiResponse(responseCode = "404", description = "反馈未找到"),
            @ApiResponse(responseCode = "500", description = "服务器内部错误")
    })
    @PutMapping("/{id}/process")
    @PreAuthorize("hasRole('管理员')") // 只有管理员能处理反馈
    public ResponseResult<Void> processFeedback(
            @Parameter(description = "反馈ID", required = true, example = "1") @PathVariable Long id,
            @Parameter(description = "新的处理状态", required = true, example = "已解决", schema = @Schema(implementation = FeedbackStatusEnum.class))
            @RequestParam String statusStr,
            @Parameter(description = "管理员回复", example = "问题已修复，感谢您的反馈。")
            @RequestParam(required = false) String reply) {

        // 转换状态字符串为枚举，如果无效则 fromDescription 抛出 IllegalArgumentException
        FeedbackStatusEnum newStatus = FeedbackStatusEnum.fromDescription(statusStr);

        boolean success = feedbackService.updateFeedbackStatusAndReply(id, newStatus, reply);
        if (!success) { // 如果 Service 返回 false
            // 细化失败原因，如果 Service 返回 false
            Optional.ofNullable(feedbackService.getById(id)) // 尝试获取原始反馈判断是否存在
                    .ifPresentOrElse(
                            existingFeedback -> { throw new BusinessException(HttpStatusEnum.BAD_REQUEST.getCode(), "反馈处理失败，请稍后重试。"); }, // 存在但更新失败
                            () -> { throw new BusinessException((HttpStatusEnum.NOT_FOUND.getCode()),"反馈未找到。"); } // 不存在
                    );
        }
        return ResponseResult.success(HttpStatusEnum.SUCCESS.getCode(), "反馈处理成功", null);
    }
}